/********************************************************************** * * Copyright (C) 2008 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import java.util.regex.Pattern; import java.util.regex.Matcher; import jxl.Sheet; import jxl.Cell; import jxl.CellType; import jxl.LabelCell; /** * Refactorisation to provide more sophisticated find cell by contents * functionality */ public class CellFinder { private Sheet sheet; public CellFinder(Sheet s) { sheet = s; } /** * Gets the cell whose contents match the string passed in. * If no match is found, then null is returned. The search is performed * on a row by row basis, so the lower the row number, the more * efficiently the algorithm will perform * * @param contents the string to match * @param firstCol the first column within the range * @param firstRow the first row of the range * @param lastCol the last column within the range * @param lastRow the last row within the range * @param reverse indicates whether to perform a reverse search or not * @return the Cell whose contents match the parameter, null if not found */ public Cell findCell(String contents, int firstCol, int firstRow, int lastCol, int lastRow, boolean reverse) { Cell cell = null; boolean found = false; int numCols = lastCol - firstCol; int numRows = lastRow - firstRow; int row1 = reverse ? lastRow : firstRow; int row2 = reverse ? firstRow : lastRow; int col1 = reverse ? lastCol : firstCol; int col2 = reverse ? firstCol : lastCol; int inc = reverse ? -1 : 1; for (int i = 0; i <= numCols && found == false; i++) { for (int j = 0; j <= numRows && found == false; j++) { int curCol = col1 + i * inc; int curRow = row1 + j * inc; if (curCol < sheet.getColumns() && curRow < sheet.getRows()) { Cell c = sheet.getCell(curCol, curRow); if (c.getType() != CellType.EMPTY) { if (c.getContents().equals(contents)) { cell = c; found = true; } } } } } return cell; } /** * Finds a cell within a given range of cells * * @param contents the string to match * @return the Cell whose contents match the parameter, null if not found */ public Cell findCell(String contents) { Cell cell = null; boolean found = false; for (int i = 0 ; i < sheet.getRows() && found == false; i++) { Cell[] row = sheet.getRow(i); for (int j = 0 ; j < row.length && found == false; j++) { if (row[j].getContents().equals(contents)) { cell = row[j]; found = true; } } } return cell; } /** * Gets the cell whose contents match the regular expressionstring passed in. * If no match is found, then null is returned. The search is performed * on a row by row basis, so the lower the row number, the more * efficiently the algorithm will perform * * @param pattern the regular expression string to match * @param firstCol the first column within the range * @param firstRow the first row of the range * @param lastCol the last column within the range * @param lastRow the last row within the range * @param reverse indicates whether to perform a reverse search or not * @return the Cell whose contents match the parameter, null if not found */ public Cell findCell(Pattern pattern, int firstCol, int firstRow, int lastCol, int lastRow, boolean reverse) { Cell cell = null; boolean found = false; int numCols = lastCol - firstCol; int numRows = lastRow - firstRow; int row1 = reverse ? lastRow : firstRow; int row2 = reverse ? firstRow : lastRow; int col1 = reverse ? lastCol : firstCol; int col2 = reverse ? firstCol : lastCol; int inc = reverse ? -1 : 1; for (int i = 0; i <= numCols && found == false; i++) { for (int j = 0; j <= numRows && found == false; j++) { int curCol = col1 + i * inc; int curRow = row1 + j * inc; if (curCol < sheet.getColumns() && curRow < sheet.getRows()) { Cell c = sheet.getCell(curCol, curRow); if (c.getType() != CellType.EMPTY) { Matcher m = pattern.matcher(c.getContents()); if (m.matches()) { cell = c; found = true; } } } } } return cell; } /** * Gets the cell whose contents match the string passed in. * If no match is found, then null is returned. The search is performed * on a row by row basis, so the lower the row number, the more * efficiently the algorithm will perform. This method differs * from the findCell methods in that only cells with labels are * queried - all numerical cells are ignored. This should therefore * improve performance. * * @param contents the string to match * @return the Cell whose contents match the paramter, null if not found */ public LabelCell findLabelCell(String contents) { LabelCell cell = null; boolean found = false; for (int i = 0; i < sheet.getRows() && !found; i++) { Cell[] row = sheet.getRow(i); for (int j = 0; j < row.length && !found; j++) { if ((row[j].getType() == CellType.LABEL || row[j].getType() == CellType.STRING_FORMULA) && row[j].getContents().equals(contents)) { cell = (LabelCell) row[j]; found = true; } } } return cell; } }